﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Windows;
using System.Diagnostics;
using System.IO;
using System.Xml;


using System.Xml.Serialization;


namespace AI
{


    public class DestInfo
    {

        public Vector StartPoint { get { return _StartPoint; } set { _StartPoint = value; } }
        Vector _StartPoint = new Vector();

        public Vector StartDir { get { return _StartDir; } set { _StartDir = value; } }
        Vector _StartDir = new Vector();
        public Vector GetNormalDir()
        {
            Vector dir = new Vector(_StartDir.X, _StartDir.Y);
            double len = 1.0 / dir.Length;
            _StartDir.X = len * _StartDir.X;
            _StartDir.Y = len * _StartDir.Y;
            return dir;
        }

        public Vector EndPoint { get { return _EndPoint; } set { _EndPoint = value; } }
        //public Vector _EndPoint = new Vector(0,0);
        public Vector _EndPoint = new Vector(122.32428, 47.600605);


    }

    public class PathInfo<T>
    {
        // 거쳐가야하는 지점
        public List<T> _NodeList = new List<T>();

        // 최종경로
        public List<T> _TotalNodeList = new List<T>();

        public double _Weight = 0; // 토탈비용
        //
        

    }

    public class PathInfo2
    {
        public Path _Path = null;
        public int _Count = 0;
    }

    public class MapInfoManager
    {
        /// <summary>
        /// 최종목적지 저장된곳
        /// </summary>
        public PathInfo<int> _BestNodePath;
        public int _NextCount = 0;

        public PathInfo2 _PathInfo = null;

        public Point GetNextPoint()
        {
            if (_BestNodePath._TotalNodeList.Count <= _NextCount)
                return null;

            Node node = _BaseNode._NodeList[_BestNodePath._TotalNodeList[_NextCount++]];
            return _BaseNode._PointList[node._EIndex];
        }




        public Point GetNextPoint2()
        {


            if (_PathInfo._Path.Count <= _PathInfo._Count)
                return null;

            int index = _PathInfo._Path[_PathInfo._Count++];

            //Node node = _BaseNode._NodeList[_BestNodePath._TotalNodeList[_NextCount++]];
            return _BaseNode._PointList[index];
        }

        

        /// <summary>
        ///  남은수 다음포인트수
        /// </summary>
        /// <returns></returns>
        public int GetRestNextCount()
        {
            return _BestNodePath._TotalNodeList.Count - _NextCount;
        }


        public List<int> _KiaPoint = new List<int>();

        public MapInfoManager()
        {
            //_KiaPoint.Add(2);
            //_KiaPoint.Add(3);
            //_KiaPoint.Add(4);
            //_KiaPoint.Add(5);
        }

        //public NodeManager _KiaNode = new NodeManager();


        //public PathInfo<int> MakePath2(double dx, double dy)
        //{

            
        //    double minWeight = double.MaxValue;

        //    Point endPoint = _BaseNode.GetPoint(dx, dy);
            
        //    List<Node> endNodeList = new List<Node>();

        //    foreach(Node Node in _BaseNode._NodeList.Values)
        //    {
        //        if( Node._EIndex == endPoint.e
        //    }

            

        //    // 시작노드 설정
        //    Node StartNode = _BaseNode._NodeList[58];



        //    WayInfo wayInfo = _BaseNode.MakePath(StartNode, nodeIndex);


        //    foreach (PathInfo<int> pathInfo in _candiPathList)
        //    {

        //        // 각패스테스트를 위한 임시 시작노드 생성
        //        Node tempStartNode = StartNode;


        //        //토탈 포인트 리스트에 시작위치를 셋팅 
        //        pathInfo._TotalNodeList.Add(StartNode._Index);

        //        foreach (int nodeIndex in pathInfo._NodeList)
        //        {
        //            WayInfo wayInfo = _BaseNode.MakePath(tempStartNode, nodeIndex);

        //            pathInfo._Weight += wayInfo._Weight;

        //            int count = wayInfo._Path.Count;
        //            for (int i = 0; i < count; i++)
        //            {
        //                int wayIndex = wayInfo._Path.Pop();
        //                pathInfo._TotalNodeList.Add(wayIndex);
        //            }

        //            // 경유지 포인트를 찾기위해 생 시작위치 셋팅

        //            tempStartNode = _BaseNode._NodeList[wayInfo._EndNodeIndex];//_BaseNode.GetNode(wayInfo._EndIndex[ 0],    wayInfo._EndIndex[ 1]);
        //        }

        //        if (pathInfo._Weight < minWeight)
        //        {
        //            minWeight = pathInfo._Weight;
        //            _BestNodePath = pathInfo;
        //        }

        //    }

        //    _NextCount = 0;
        //    return _BestNodePath;
        //}

        public Path MakePath(double dx, double dy)
        {
            _PathInfo = new PathInfo2();

            _PathInfo._Path = _BaseNode.MakePath(dx, dy);
            _PathInfo._Count = 0;
            return _PathInfo._Path;
        }


        public PathInfo<int> MakePath(double sx, double sy, Vector curDir, double dx, double dy)
        {




            double minWeight = double.MaxValue;

            Point endPoint = _BaseNode.GetPoint(dx,dy);

            //
            List<int> []  _KiaPointNodeList = new List<int> [4];

            for(int i = 0;i< _KiaPoint.Count;++i)
            {
                _KiaPointNodeList[i] = new List<int>();
                foreach(Node node in _BaseNode._NodeList.Values)
                {
                    if( node._EIndex == _KiaPoint[ i])
                    {
                        _KiaPointNodeList[i].Add(node._Index);
                    }
                }
            }

            List<int> _EndNodeList = new List<int>();

            foreach (Node node in _BaseNode._NodeList.Values)
            {
                if (node._EIndex == endPoint._index)
                {
                    _EndNodeList.Add(node._Index);
                }
            }


            List<int> _indexList = new List<int>();
            _indexList.Add(0);
            _indexList.Add(1);
            _indexList.Add(2);
            _indexList.Add(3);

            List<List<int>> PermuList = PermuteUtils.ShowPermutations<int>( _indexList, 4);

            List<PathInfo<int>> _candiPathList = new List<PathInfo<int>>();

            foreach (List<int> Permu in PermuList)
            {
                

                foreach (int nodeIndex0 in _KiaPointNodeList[Permu[0]])
                {
                    foreach (int nodeIndex1 in _KiaPointNodeList[Permu[1]])
                    {
                        foreach (int nodeIndex2 in _KiaPointNodeList[Permu[2]])
                        {
                            foreach (int nodeIndex3 in _KiaPointNodeList[Permu[3]])
                            {
                                foreach(int endNode in _EndNodeList)
                                {
                                    PathInfo<int> _PathInfo = new PathInfo<int>();

                                    _PathInfo._NodeList.Add(nodeIndex0);
                                    _PathInfo._NodeList.Add(nodeIndex1);
                                    _PathInfo._NodeList.Add(nodeIndex2);
                                    _PathInfo._NodeList.Add(nodeIndex3);
                                    _PathInfo._NodeList.Add(endNode);

                                    _candiPathList.Add(_PathInfo);


                                }
                            }

                        }

                    }

                }
            }



            // 시작노드 설정
            Node StartNode = _BaseNode.GetShortestNode(sx,sy,curDir);

            foreach (PathInfo<int> pathInfo in _candiPathList)
            {

                // 각패스테스트를 위한 임시 시작노드 생성
                Node tempStartNode = StartNode;


                //토탈 포인트 리스트에 시작위치를 셋팅 
                pathInfo._TotalNodeList.Add(StartNode._Index);

                foreach(int nodeIndex in pathInfo._NodeList)
                {
                    WayInfo wayInfo = _BaseNode.MakePath(tempStartNode, nodeIndex);

                    pathInfo._Weight += wayInfo._Weight;
                    
                    int count = wayInfo._Path.Count;
                    for(int i = 0; i < count ;i++)
                    {
                        int wayIndex = wayInfo._Path.Pop();
                        pathInfo._TotalNodeList.Add(wayIndex);
                    }

                    // 경유지 포인트를 찾기위해 생 시작위치 셋팅

                    tempStartNode = _BaseNode._NodeList[wayInfo._EndNodeIndex];//_BaseNode.GetNode(wayInfo._EndIndex[ 0],    wayInfo._EndIndex[ 1]);
                }

                if (pathInfo._Weight < minWeight)
                {
                    minWeight = pathInfo._Weight;
                    _BestNodePath = pathInfo;
                }
                
            }

            _NextCount = 0;
            return _BestNodePath;
        }

        public NodeManager _BaseNode = new NodeManager();


        

        public void Save()
        {
            _BaseNode.Save();

            XmlSerializer s = new XmlSerializer(_KiaPoint.GetType());
            TextWriter w = new StreamWriter(@"robochamps/urban/AI/KIAPoint.xml");
            s.Serialize(w, _KiaPoint);
            w.Close();

            
        }

        public void Load()
        {
            _BaseNode.Load();

            try
            {
                XmlSerializer s = new XmlSerializer(_KiaPoint.GetType());
                using (TextReader r = new StreamReader(@"robochamps/urban/AI/KIAPoint.xml"))
                {
                    List<int> KIAPointList = (List<int>)s.Deserialize(r);
                    if (KIAPointList != null)
                        _KiaPoint = KIAPointList;

                }


            }
            catch
            {

            }

            

        }

    }
}
